package com.jellyfishumbrella.GL;

import java.util.LinkedHashSet;

import org.lwjgl.util.vector.Vector3f;

import com.jellyfishumbrella.util.EqualsUtil;
import com.jellyfishumbrella.util.HashCodeUtil;

public class Vertex implements Cloneable {// extends Vector3d implements Cloneable {
	// private static long nextSerialID = 0;
	// private long serialID = nextSerialID++;
	public UberPoly.VertexLODTag	vertexLODType		= UberPoly.VertexLODTag.UNDEFINED;

	public Vector3d					coord				= new Vector3d();
	private int						index				= -1;
	int								useCount			= 0;
	public Normal					normal				= new Normal();
	public GLColor					glColor				= new GLColor();
	public Vector2d					uv					= new Vector2d(0.0, 0.1);
	public boolean					isSelected			= false;
	public int						VBOIndexStart		= 0;
	public LinkedHashSet<UberPoly>	connectedUberPolys	= new LinkedHashSet<UberPoly>();

	public Vertex() {
		super();
	}

	public Vertex(double X, double Y, double Z) {
		// super(X, Y, Z);
		coord = new Vector3d(X, Y, Z);
	}

	public Vertex(Vector3d p) {
		super();
		coord = p.clone();
	}

	public Vector3f toGL() {
		Vector3f v = new Vector3f();
		v.x = (float) x();
		v.y = (float) y();
		v.z = (float) z();
		return v;
	}

	public Vertex clone() {
		Vertex newVert = new Vertex(x(), y(), z());
		newVert.index = index;
		newVert.useCount = useCount;
		newVert.VBOIndexStart = VBOIndexStart;
		newVert.normal = normal.clone();
		newVert.glColor = glColor.clone();
		newVert.uv = uv.clone();
		newVert.isSelected = isSelected;

		return newVert;
	}

	public String toString() {
		return index + " || " + toGL().toString();
	}

	public void setX(double X) {
		coord.x = X;
	}

	public void setY(double Y) {
		coord.y = Y;
	}

	public void setZ(double Z) {
		coord.z = Z;
	}

	public double x() {
		return coord.x;
	}

	public double y() {
		return coord.y;
	}

	public double z() {
		return coord.z;
	}

	public void add(Vertex currVert) {
		coord.add(currVert.coord);
	}

	public void scale(double d) {
		coord.scale(d);
	}

	public void sub(Vertex currVert) {
		coord.sub(currVert.coord);
	}

	public void add(Vector3d translation) {
		coord.add(translation);
	}

	public int getIndex() {
		return index;
	}

	public void setIndex(int index) {
		this.index = index;
		if (index <= 0) {
			System.out.println("STOP!  Index = " + this.toString());
		}
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + VBOIndexStart;
		result = prime * result + ((coord == null) ? 0 : coord.hashCode());
		result = prime * result + ((glColor == null) ? 0 : glColor.hashCode());
		result = prime * result + index;
		result = prime * result + ((normal == null) ? 0 : normal.hashCode());
		result = prime * result + ((uv == null) ? 0 : uv.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Vertex other = (Vertex) obj;
		if (VBOIndexStart != other.VBOIndexStart)
			return false;
		if (coord == null) {
			if (other.coord != null)
				return false;
		} else if (!coord.equals(other.coord))
			return false;
		if (glColor == null) {
			if (other.glColor != null)
				return false;
		} else if (!glColor.equals(other.glColor))
			return false;
		if (index != other.index)
			return false;
		if (normal == null) {
			if (other.normal != null)
				return false;
		} else if (!normal.equals(other.normal))
			return false;
		if (uv == null) {
			if (other.uv != null)
				return false;
		} else if (!uv.equals(other.uv))
			return false;
		return true;
	}
}
